package com.lxd.milktea.service.impl;

import com.lxd.milktea.VO.MaterialVO;
import com.lxd.milktea.dao.ProductReRepository;
import com.lxd.milktea.dao.ProductRepository;
import com.lxd.milktea.dataobject.Material;
import com.lxd.milktea.dataobject.ProductInfo;
import com.lxd.milktea.dataobject.ProductRe;
import com.lxd.milktea.dto.CartDTO;
import com.lxd.milktea.enums.ProductStatusEnum;
import com.lxd.milktea.enums.ResultEnum;
import com.lxd.milktea.exception.SellException;
import com.lxd.milktea.form.MaterialRe;
import com.lxd.milktea.service.MaterialService;
import com.lxd.milktea.service.ProductService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ProjectName: milktea
 * @Package: com.lxd.milktea.service.impl
 * @ClassName: ProductServiceImpl
 * @Author: carrymaniac
 * @Description:
 * @Date: 2020/5/3 1:10 下午
 * @Version:
 */
@Service
public class ProductServiceImpl implements ProductService {
    private final ProductReRepository productReRepository;
    private final ProductRepository productRepository;
    private final MaterialService materialService;
    public ProductServiceImpl(ProductRepository productRepository, ProductReRepository productReRepository, MaterialService materialService) {
        this.productRepository = productRepository;
        this.productReRepository = productReRepository;
        this.materialService = materialService;
    }

    @Override
    public ProductInfo findOne(String productId) {
        Optional<ProductInfo> byId = productRepository.findById(productId);
        if(byId.isPresent()){
            return byId.get();
        }else {
            throw new SellException(ResultEnum.PRODUCT_NOT_EXIST);
        }
    }

    @Override
    public List<ProductInfo> findUpAll() {
        return  productRepository.findAllByProductStatus(ProductStatusEnum.UP.getCode());
    }

    @Override
    @Transactional
    public void increaseStock(List<CartDTO> cartDTOS) {
        for(CartDTO cartDTO:cartDTOS ){
            Optional<ProductInfo> byId = productRepository.findById(cartDTO.getProductId());
            ProductInfo one = null;
            if(byId.isPresent()){
                one = byId.get();
            }
            if(one ==null){
                throw new SellException(ResultEnum.PRODUCT_NOT_EXIST);
            }
            Integer result = one.getProductStock() + cartDTO.getProductQuantity();
            one.setProductStock(result);
            productRepository.save(one);
        }
    }

    @Override
    @Transactional
    public void decreaseStock(List<CartDTO> cartDTOS) {
        for(CartDTO cartDTO:cartDTOS ){
            Optional<ProductInfo> byId = productRepository.findById(cartDTO.getProductId());
            if(!byId.isPresent()){
                throw new SellException(ResultEnum.PRODUCT_NOT_EXIST);
            }else {
                ProductInfo one = byId.get();
                if(one ==null){
                    throw new SellException(ResultEnum.PRODUCT_NOT_EXIST);
                }
                Integer result = one.getProductStock() - cartDTO.getProductQuantity();
                if(result<0){
                    throw new SellException(ResultEnum.PRODUCT_STOCK_ERROR);
                }
                one.setProductStock(result);
                productRepository.save(one);
            }
        }
    }

    @Override
    public ProductInfo save(ProductInfo productInfo) {
        return productRepository.save(productInfo);
    }


    @Override
    public Page<ProductInfo> findAll(Pageable pageable) {
        return productRepository.findAll(pageable);
    }

    @Override
    public ProductInfo onSale(String productId) {
        Optional<ProductInfo> byId = productRepository.findById(productId);
        if(byId.isPresent()){
            ProductInfo productInfo = byId.get();
            productInfo.setProductStatus(ProductStatusEnum.UP.getCode());
            return productRepository.save(productInfo);
        }else {
            throw new SellException(ResultEnum.PRODUCT_NOT_EXIST);
        }
    }

    @Override
    public ProductInfo OffSale(String productId) {
        Optional<ProductInfo> byId = productRepository.findById(productId);
        if(byId.isPresent()){
            ProductInfo productInfo = byId.get();
            productInfo.setProductStatus(ProductStatusEnum.DOWN.getCode());
            return productRepository.save(productInfo);
        }else {
            throw new SellException(ResultEnum.PRODUCT_NOT_EXIST);
        }
    }

    @Override
    public List<MaterialVO> getProductForm(String productId) {
        List<ProductRe> allMaterialRe = productReRepository.findAllByProductId(productId);
        if(allMaterialRe.isEmpty()){
            return null;
        }
        List<String> ids = allMaterialRe.stream().map(ProductRe::getMaterialId).collect(Collectors.toList());
        List<Material> list = materialService.findList(ids);
        HashMap<String,Material> materialMap = new HashMap<>();
        list.stream().forEach(material -> {
            materialMap.put(material.getId(),material);
        });
        //查询到所需要的一级原料
        HashMap<String,Integer> result = new HashMap<>();
        allMaterialRe.stream().forEach(re -> {
            //所需的底层材料 ID + 单位为1的数量
            HashMap<String, Integer> oneForm = materialService.findOneForm(re.getMaterialId());
            //乘上数量
            Set<String> keys = oneForm.keySet();
            for(String key:keys){
                result.merge(key,oneForm.get(key)*re.getNeedNum(),(oldVal,newVal)-> oldVal+newVal);
            }
        });
        ArrayList idList = new ArrayList(result.keySet());
        list = materialService.findList(idList);
        List<MaterialVO> materialVOList = list.stream().map(material -> {
            MaterialVO vo = new MaterialVO();
            BeanUtils.copyProperties(material,vo);
            vo.setNeedNum(result.get(material.getId()));
            return vo;
        }).collect(Collectors.toList());
        //得到合并好的result,最后查询原料的信息 拼接为VO出来
        return materialVOList;
    }

    @Override
    public List<ProductRe> saveProductRe(String productId, List<MaterialRe> list) {
        List<ProductRe> collect = list.stream().map(m -> {
            ProductRe p = new ProductRe();
            p.setProductId(productId);
            p.setMaterialId(m.getMaterialId());
            p.setNeedNum(m.getNum());
            return p;
        }).collect(Collectors.toList());
        //保存
        return productReRepository.saveAll(collect);
    }

    @Override
    public void deleteProductRe(String productId) {
        productReRepository.deleteAllByProductId(productId);
    }

    @Override
    public List<ProductRe> findProductRe(String productId) {
        return productReRepository.findAllByProductId(productId);
    }
}
